package com.google.code.ptrends.common;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import com.google.code.ptrends.common.entities.EventType;
import com.google.code.ptrends.common.entities.Session;
import com.google.code.ptrends.locators.LocatorFactory;
import com.google.code.ptrends.locators.implementations.LocatorFactoryImpl;
import com.google.code.ptrends.services.DataService;
import com.google.code.ptrends.services.SessionService;
import com.google.code.ptrends.services.SupplierService;
import com.google.code.ptrends.services.implementations.DatabaseSessionService;
import com.google.code.ptrends.services.implementations.ETLService;
import com.google.code.ptrends.services.implementations.XmlSupplierService;
import com.google.code.ptrends.services.implementations.dataservice.DataServiceImpl;

public class RetJob implements Job {

	private static final Logger LOG = Logger.getLogger(RetJob.class);
	private static final String CONNECTION_STRING = "jdbc:derby://127.0.0.1:1527/myDB;create=true";
	private static final String LOGIN = "app";
	private static final String PASS = "qwerty";
	private Connection connection = null;

	@Override
	public void execute(final JobExecutionContext arg0)
			throws JobExecutionException {
		connection = buildConnection();
		try {
			final DataService dataService = createDataService();
			final SessionService sessionService = createSessionService(dataService);

			Session session = sessionService
					.createSession(SupplierIdentifiers.RET);
			session.addEvent("ETL Session start", "Started ETL process",
					EventType.OK);
			session.addEvent("Service init", "Started services initialization",
					EventType.OK);

			final SupplierService supplierService = createSupplierService();
			final LocatorFactory locatorFactory = createLocatorFactory();
			final ProcessorBuilder processorBuilder = createProcessorBuilder(session);

			LOG.info("Started creating ETLService");

			final ETLService service = new ETLService(locatorFactory,
					supplierService, processorBuilder, dataService);

			session.addEvent("Services initialized",
					"All services has been initialized", EventType.OK);

			LOG.info("Started importing source data");

			service.serve(SupplierIdentifiers.RET, session);

			session.addEvent("ETL process finished", "", EventType.OK);
			sessionService.saveSession(session);

			LOG.info("Import completed");
		} catch (SQLException e) {
			LOG.error("Error in job execution", e);
		} finally {
			if (connection != null) {
				try {
					connection.close();
				} catch (SQLException e) {
					LOG.error("Error closing connection", e);
				}
			}
		}
	}

	private LocatorFactory createLocatorFactory() {
		LOG.info("Started creating locator factory");
		return new LocatorFactoryImpl();
	}

	private SupplierService createSupplierService() {
		LOG.info("Started creating supplier service");
		return new XmlSupplierService();
	}

	private ProcessorBuilder createProcessorBuilder(Session session) {
		LOG.info("Started creating processor builder");
		return new ProcessorBuilderImpl(session);
	}

	private DataService createDataService() {
		LOG.info("Started creating data service");
		return new DataServiceImpl(connection);
	}

	private SessionService createSessionService(DataService dataService) {
		LOG.info("Started creating session service");
		return new DatabaseSessionService(dataService);
	}

	private Connection buildConnection() {
		Connection conn = null;
		try {
			Class.forName(REAL_DB_DRIVER);
			conn = DriverManager.getConnection(REAL_DB_URL);
		} catch (Exception e) {
			LOG.error("Cannot build connection", e);
		}
		return conn;
	}

	private static final String REAL_DB_URL = "jdbc:derby://localhost:1527/myDB;create=true";
	private static final String REAL_DB_DRIVER = "org.apache.derby.jdbc.ClientDriver";

}
